package org.jeecg.modules.third.jg.report.information.utils;

import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.jdom2.Element;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class XmlUtils {
    public static String converTomXml(Object obj) {
//        return converToXml(obj,"UTF-8");
        return converToXml(obj,"gbk");

    }

    private static String converToXml(Object obj, String encoding) {
        String result = null;
        try {
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            // 去掉生成xml的默认报文头
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
            // xml格式,false,不带格式，
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
//            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING,encoding);
            StringWriter writer = new StringWriter();
            marshaller.marshal(obj,writer);
            result =writer.toString();

      /*      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            StringWriter writerlog = new StringWriter();
            marshaller.marshal(obj,writerlog);
            System.out.println("发送数据：" + writerlog.toString());*/
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static<T> T converyToJavaBean(String xml,Class<T> c){
        T t = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            t = (T)unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }


    /**
     * xml 转 对象
     *
     * @param clazz
     * @param xmlStr
     * @return
     * @throws Exception
     */
    public static Object dataXmltoEntity(Class<?> clazz, String xmlStr) {
        if (clazz == null) {
            System.out.println("未设置对象的类型");
            return null;
        }
        File file = new File(xmlStr);
        if (!file.exists()) {
            System.out.println("解析失败，找不到文件");
            return null;
        }
        //创建Jdom2的解析器对象
        SAXBuilder builder = new SAXBuilder();
        Document document = null;
        org.jdom.Element root = null;
        Object obj = null;
        try {
            document = builder.build(file.getAbsoluteFile());
            root = document.getRootElement();
            if (!root.getName().equals(clazz.getSimpleName())) {
                System.out.println("xml内容无法转成 " + clazz + "对象，请检查！");
                return null;
            }
            // new出 当前最大的对象
            obj = clazz.getConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("无法进行xml解析，请检查！");
        }
        try {
            List<Element> children = root.getChildren();
            for (Element child : children) {
                // 第二层的xml数据
                List<Element> children1 = child.getChildren();
                if (children1.isEmpty()) { // 处理第一层的xml数据
                    Field field = clazz.getDeclaredField(child.getName());
                    field.setAccessible(true);
                    if (field.getGenericType().getTypeName().equals("int")) {
                        field.set(obj, Integer.parseInt(child.getValue()));
                    } else {
                        field.set(obj, child.getValue());
                    }
                } else { // 处理第二层的 xml 数据
                    mm(clazz, obj, child, children1);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("解析xml数据转换成实体出现异常：" + e.getMessage());
        }
        return obj;
    }

    private static void mm(Class<?> clazz, Object obj, Element child, List<Element> children1) throws Exception {
        // 取到当前的 list 属性
        Field field = clazz.getDeclaredField(child.getName());
        field.setAccessible(true);
        Class<?> genericClazz = null;
        if (field.getType() == List.class) {
            // 如果是List类型，得到其Generic的类型
            Type genericType = field.getGenericType();
            if (genericType != null) {
                // 如果是泛型参数的类型
                if (genericType instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) genericType;
                    //得到泛型里的class类型对象
                    genericClazz = (Class<?>) pt.getActualTypeArguments()[0];
                }
            }
        }
        if (genericClazz != null) {
            List list = new ArrayList();
            // list 中 包含的对象
            for (Element element : children1) {
                // 取出当前类的属性与值
                List<Element> children2 = element.getChildren();
                // new 出List中包含的对象
                Object o = genericClazz.getConstructor().newInstance();
                // 当前对象进行赋值
                for (Element element1 : children2) {
                    if (element1.getChildren().isEmpty()) {
                        Field field1 = genericClazz.getDeclaredField(element1.getName());
                        field1.setAccessible(true);
                        field1.set(o, element1.getValue());
                    } else {
                        // 递归处理
                        mm(genericClazz, o, element1, element1.getChildren());
                    }
                }
                list.add(o);
            }
            field.set(obj, list);
        }
    }
}

